Перейти к основному содержимому

5.05. Переменные

Разработчику Архитектору

Переменные

Переменные

Переменная (Variable) – это именованное место в памяти, где хранится значение определённого типа. на позволяет программе запоминать, использовать и изменять данные в процессе выполнения.

Определение:

  • тип данных: определяет, какие данные может хранить переменная (int, string, bool и т.д.);
  • имя: уникальный идентификатор, по которому к переменной можно обратиться;
  • значение: то, что хранится в переменной (например, 25).

Объявление и инициализация переменной:

int age;             // Объявление
age = 25; // Инициализация

string message = "Добро пожаловать"; // Одновременное объявление и инициализация

Здесь:

  • int, string - тип;
  • age, message - имя;
  • 25, “Добро пожаловать” - значение.

Синтаксис прост:

тип имя = значение; // инициализация

или

тип имя; // объявление
имя = значение; // присваивание

Переменная должна быть инициализирована, прежде чем использоваться (если только это не out-параметр).

Где можно использовать переменную — зависит от области видимости (scope).

Локальные переменные объявляются внутри методов, циклов или блоков и доступны только в пределах блока {…}, в котором они созданы:

void PrintGreeting()
{
string message = "Привет!"; // локальная переменная
Console.WriteLine(message);
} // message уничтожается здесь

if (true)
{
int x = 10;
Console.WriteLine(x); // OK
}
// Console.WriteLine(x); // ОШИБКА: x не существует

В C# нет глобальных переменных, как в C или Python. Но есть статические поля класса, которые по сути ведут себя как «глобальные»:

public class AppState
{
public static string CurrentUser = "admin";
}

Доступ: AppState.CurrentUser. Чрезмерное использование таких полей — антипаттерн (нарушает инкапсуляцию). Обычно можно сделать отдельный статический класс, например, констант, который будет хранить набор чего-то статического для сравнения.

Кстати о константах.

Константы (Constants) – значения, которые не могут быть изменены во время выполнения программы.

Синтаксис:

const тип Имя = значение;

Константы должны быть инициализированы при объявлении, и являются статическими по умолчанию (принадлежат классу, а не объекту). Значение подставляется на этапе компиляции (не занимает память во время выполнения). Поддерживает только примитивные типы, string, и enum. И константа является статической по умолчанию (принадлежит типу, а не экземпляру).

Отличие от переменной также в том, что константа не требует памяти – значение подставляется компилятором. Это нужно для фиксированных значений.

При работе с переменными, нужно использовать описательные имена, которые дадут понять, что они собой представляют – username, totalPrice, а не x, y.

C# позволяет не указывать тип явно, если он очевиден из правой части выражения.

Если тип очевиден из контекста, можно объявить через var:

var имя = значение;

И это самое распространённое, очень часто можно увидеть именно такой вид - var:

var list = new List<string>(); // тип string понятен
var age = 25; // int
var name = "Alice"; // string
var list = new List<int>(); // List<int>

Если тип неочевиден, лучше предусмотреть и строго типизировать. К примеру:

var result = GetData(); // Что за тип? int? string? object?

Правило: var — не динамический тип. Это синтаксический сахар. Тип определяется на этапе компиляции и не меняется. Помните, что язык C# не динамически типизированный, а строго - это значит, что есть требования к указаниям типов.

Модификаторы параметров: ref, out, in, params управляют тем, как параметры передаются в методы.

ref — передача по ссылке (с возможностью изменения). Переменная должна быть инициализирована до передачи. Метод может изменить её значение.

void DoubleValue(ref int x)
{
x *= 2;
}

int number = 5;
DoubleValue(ref number); // number = 10

Полезно, когда нужно изменить исходную переменную.

out — выходной параметр. Переменная не обязана быть инициализирована при передаче, но должна быть присвоена внутри метода.

bool TryParse(string input, out int result)
{
if (int.TryParse(input, out result))
return true;
else
{
result = 0;
return false;
}
}

if (TryParse("123", out int value))
{
Console.WriteLine(value); // 123
}

Идеально для методов, возвращающих результат и статус (например, TryParse).

Ключевые слова ref и out используются для передачи аргументов в методы по ссылке, что позволяет изменять значение переменной внутри метода и сохранять эти изменения после завершения метода. ref - когда нужно передать уже существующее значение в метод и позволить методу изменить его, out - когда метод должен вернуть несколько значений (например, для возврата результата и состояния ошибки).

in — передача по ссылке, только для чтения (C# 7.2+). Позволяет передавать большие структуры по ссылке, но запрещает их изменение.

void PrintPerson(in Person person)
{
Console.WriteLine(person.Name);
// person.Name = "xxx"; // ОШИБКА: нельзя изменять
}

var p = new Person { Name = "Bob" };
PrintPerson(in p);

Эффективно для производительности: избегает копирования, но безопасно.

params — переменное число аргументов. Позволяет передавать произвольное количество аргументов одного типа.

void PrintNumbers(params int[] numbers)
{
foreach (int n in numbers)
Console.WriteLine(n);
}

PrintNumbers(1, 2, 3, 4); // OK
PrintNumbers(); // OK — пустой массив

Что можно хранить в переменной?

  • Переменная может содержать:
  • Примитивные значения: int, bool, double, char;
  • Ссылки на объекты: string, List<T>, MyClass;
  • Результат вызова метода
var length = GetName().Length;
var user = CreateUser();
  • Анонимные объекты:
var person = new { Name = "Alice", Age = 30 };
  • Функции (делегаты):
Func<int, int> square = x => x * x;

Переменные используются также в циклах.

foreach (var item in items)
{
Console.WriteLine(item);
}

Здесь item - локальная переменная, объявленная на каждой итерации. Она копируется из коллекции:

  • Для значимых типов (int, struct) — копируется значение.
  • Для ссылочных типов (class) — копируется ссылка (объект общий).

Изменение item не повлияет на коллекцию. Для foreach по массиву item — readonly. Чтобы изменить элемент, используйте for.